package com.liuyjy.encryptDecrypt;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.io.IOException;

/**
 * @Author liuyjy
 * @Date 2025/2/20 9:42
 * @Description:  动态序反序列化器
 **/
@Slf4j
public class DynamicCryptoDeserializer extends JsonDeserializer<Object> {
    private final CryptoProvider provider;
    private final Decrypt decryptMeta;
    private final Encrypt encryptMeta;

    public DynamicCryptoDeserializer(CryptoProvider provider, Decrypt decryptMeta) {
        this.provider = provider;
        this.decryptMeta = decryptMeta;
        this.encryptMeta = null;
    }

    public DynamicCryptoDeserializer(CryptoProvider provider, Encrypt encryptMeta) {
        this.provider = provider;
        this.encryptMeta = encryptMeta;
        this.decryptMeta = null;
    }

    @Override
    public Object deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException {
        // 获取字段的当前值
        Object value = parseValue(p, ctxt);
        if (value == null) return null;

        // 动态检查开关状态
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes != null) {
            Boolean enabled = (Boolean) requestAttributes.getAttribute(
                    "CRYPTO_ENABLED", RequestAttributes.SCOPE_REQUEST);
            if (enabled != null && enabled) {
                try {
                    // 处理加解密逻辑
                    String processedValue = processValue(value.toString());
                    return convertValue(processedValue, ctxt.getContextualType());
                } catch (Exception e) {
                    throw new JsonMappingException(p, "Crypto process failed", e);
                }
            }
        }

        // 如果开关未启用，直接返回原始值
        return value;
    }

    /**
     * 根据字段类型解析值
     */
    private Object parseValue(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonToken token = p.currentToken();
        if (token == JsonToken.VALUE_STRING) {
            return p.getText();
        } else if (token == JsonToken.VALUE_NUMBER_INT) {
            return p.getIntValue();
        } else if (token == JsonToken.VALUE_NUMBER_FLOAT) {
            return p.getDoubleValue();
        } else if (token == JsonToken.VALUE_TRUE || token == JsonToken.VALUE_FALSE) {
            return p.getBooleanValue();
        } else if (token == JsonToken.VALUE_NULL) {
            return null;
        } else if (token == JsonToken.START_OBJECT || token == JsonToken.START_ARRAY) {
            // 嵌套对象或数组，递归处理
            return ctxt.readValue(p, ctxt.getContextualType());
        } else {
            throw new JsonMappingException(p, "Unsupported token type: " + token);
        }
    }

    private String processValue(String value) {
        if (decryptMeta != null) {
            return provider.decrypt(value, decryptMeta);
        }
        if (encryptMeta != null) {
            return provider.encrypt(value, encryptMeta);
        }
        return value;
    }

    private Object convertValue(String value, JavaType targetType) {
        Class<?> rawClass = targetType.getRawClass();
        if (rawClass == String.class) return value;
        if (rawClass == int.class || rawClass == Integer.class) return Integer.parseInt(value);
        if (rawClass == long.class || rawClass == Long.class) return Long.parseLong(value);
        if (rawClass == boolean.class || rawClass == Boolean.class) return Boolean.parseBoolean(value);
        if (rawClass == double.class || rawClass == Double.class) return Double.parseDouble(value);
        if (rawClass == float.class || rawClass == Float.class) return Float.parseFloat(value);
        if (rawClass == short.class || rawClass == Short.class) return Short.parseShort(value);
        if (rawClass == byte.class || rawClass == Byte.class) return Byte.parseByte(value);
        if (rawClass == char.class || rawClass == Character.class) return value.charAt(0);

        throw new IllegalArgumentException("Unsupported type: " + rawClass);
    }
}